package URLConnection; /**
 * Created by dycong on 2017/4/9.
 */
import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * @author amusarra
 *
 *         VM Arguments
 *
 *         -Djavax.net.debug=ssl
 *         -Djavax.net.ssl.trustStore=/Users/amusarra/Documents/workspace-myBlog/http-ssl-client-example/src/main/resources/cacerts.jks
 *         -Djavax.net.ssl.trustStorePassword=changeit
 *
 *         Documents di riferimento:
 *         	JavaTM Secure Socket Extension (JSSE) Reference Guide http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
 *         	JavaTM Secure Socket Extension (JSSE) Reference Guide http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html
 *         	Transport Layer Security (TLS) Renegotiation Issue Readme http://www.oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html
 */
public class HTTPSURLConnectionClientExample {

    private static final Logger logger = LoggerFactory.getLogger(HTTPSURLConnectionClientExample.class);
    private static List<String> targetURL = new ArrayList<String>();

    static {
        // for localhost testing only
        javax.net.ssl.HttpsURLConnection
                .setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {

                    public boolean verify(String hostname,
                                          javax.net.ssl.SSLSession sslSession) {
                        if (hostname.equals("localhost")) {
                            return true;
                        }
                        return false;
                    }
                });
    }

    /**
     *
     */
    public HTTPSURLConnectionClientExample() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
//        targetURL.add("https://www.goodreads.com/book/show/18734728-enterprise-integration-with-wso2-esb?from_search=true");
//        targetURL.add("https://www.liferay.com/it/products/liferay-portal/overview");
        targetURL.add("https://localhost:9222");

        for (String httpURL : targetURL) {
            HttpsURLConnection connection = null;
            try {
                // Create connection
                logger.info("Try to connect to the URL "
                        + httpURL
                        + " ...");
                URL url = new URL(httpURL);
                connection = (HttpsURLConnection) url.openConnection();

                // Prepare a GET request Action
                connection.setRequestMethod("GET");
                connection.setRequestProperty("User-Agent", "Antonio Musarra's Blog Java Client 1.0");
                connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml");
                connection.setRequestProperty("Accept-Language", "it-IT,it");

                connection.setUseCaches(false);
                connection.setDoOutput(true);

                // todo Create a SSL SocketFactory在这添加证书认证
                SSLSocketFactory sslSocketFactory = getFactorySimple();
                connection.setSSLSocketFactory(sslSocketFactory);
                connection.connect();
//                logger.info("HTTP Response Code {}", connection.getResponseCode());
//                logger.info("HTTP Response Message {}", connection.getResponseMessage());
//                logger.info("HTTP Content Length {}", connection.getContentLength());
//                logger.info("HTTP Content Type {}", connection.getContentType());
//                logger.info("HTTP Cipher Suite {}", connection.getCipherSuite());

               BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
                writer.write("hello world",0,11);
                writer.flush();

                Certificate[] serverCertificate = connection.getServerCertificates();

                for (Certificate certificate : serverCertificate) {
                    logger.info("Certificate Type {}", certificate.getType());

                    if (certificate instanceof X509Certificate) {
                        X509Certificate x509cert = (X509Certificate) certificate;

                        // Get subject
                        Principal principal = x509cert.getSubjectDN();
                        logger.info("Certificate Subject DN {}", principal.getName());

                        // Get issuer
                        principal = x509cert.getIssuerDN();
                        logger.info("Certificate IssuerDn {}", principal.getName());
                    }
                }

                // Close Connection
                connection.disconnect();

            } catch (Exception e) {
                if (connection != null) {
                    connection.disconnect();
                }
                logger.error(e.getMessage());
            }
        }
    }

    /**
     *
     * @return
     * @throws Exception
     */
    private static SSLSocketFactory getFactorySimple() throws Exception {
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
         String kFilepath = "F:/MyUtil/src/test/resources/client.jks";
        String keystorePassword = "storepass";
        String keyPassword = "keypass";
         String tFilepath = "F:/MyUtil/src/main/resources/trustedCerts.jks";
        String trustStorePassword = "storepass";
        sslContext.init(createKeyManagers(kFilepath, keystorePassword, keyPassword), createTrustManagers(tFilepath, trustStorePassword), new SecureRandom());
        return sslContext.getSocketFactory();
    }
    protected static KeyManager[] createKeyManagers(String filepath, String keyStoryPassWord, String keyPassWord) {
        KeyManagerFactory kmf = null;
        try (FileInputStream in = new FileInputStream(filepath)) {
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(in, keyStoryPassWord.toCharArray());
            kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keyStore, keyPassWord.toCharArray());
        } catch (KeyStoreException e) {
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (CertificateException e) {
        } catch (UnrecoverableKeyException e) {
        }
        return kmf.getKeyManagers();
    }

    protected static TrustManager[] createTrustManagers(String filepath, String keyStoryPassword) {
        TrustManagerFactory tmf = null;
        try (FileInputStream in = new FileInputStream(filepath)) {
            KeyStore trustStory = KeyStore.getInstance("JKS");
            trustStory.load(in, keyStoryPassword.toCharArray());
            tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(trustStory);
        } catch (KeyStoreException e) {
        } catch (IOException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (CertificateException e) {
        }
        return tmf.getTrustManagers();
    }
}
